#pragma once

#ifndef _SERVER_SYSTEM_SERVER_HANDLER_H_
#define _SERVER_SYSTEM_SERVER_HANDLER_H_

#include "ServerSystem\SystemHandler.h"

#include "Poco\BasicEvent.h"
#include "Poco\Net\SocketAddress.h"

#include <map>

namespace ExamSystem
{
    using Poco::BasicEvent;
    using Poco::Net::SocketAddress;

namespace Server
{    
    /**************************************************************************\
     Component:     CServerHandler
     Description:
        This class manages the connection to the root server/other server. It 
        has a FSM to record the states.
    \**************************************************************************/
    class CServerHandler : public CSystemHandler
    {
    public:
        CServerHandler(CServerSystem *serverSystem);
        ~CServerHandler(void);

    public:
        // start the FSM
        virtual void StartHandler(void);

    protected:
        // register sensitive package types
        virtual void RegisterPackageTypes(void);

        // process received package
        virtual void ProcessPackage(void);

    protected:
        // package handlers
        void ResultPackageHandler(void);
        void DatabasePackageHandler(void);
        void OrderPackageHandler(void);
        void MessagePackageHandler(void);
        void InformationPackageHandler(void);
        void RedirectPackageHandler(void);
        void IDAllocPackageHandler(void);

    public:
        // events
        BasicEvent<void *const> eventVersionCheckFailed;
        BasicEvent<void *const> eventSystemIDUpdated;
        BasicEvent<SocketAddress> eventConnectionRedirected;
        BasicEvent<void *const> eventReady;

    protected:
        enum ConnectionState {
            stateStart,
            stateCheckingSystemVersion,
            stateRedirecting,
            stateCheckingDataBase,
            stateReceivingDataBase,
            stateReady
        };
        ConnectionState m_presentState;

        typedef void (CServerHandler::*PackageHandler)(void);
        std::map<std::string, PackageHandler> m_packageHandlers;
    };
}
}
#endif